
#include "project.h"

// CTF's RSA key. This is created at server start up; see main()
static RSA *CTF_Key = NULL;


static BN_CTX *bn_ctx = NULL;

// we have one of these structs for each voter participating in the election.
// this entry is created when a voter submits his tallying key (Ev) with a 
// valid CTF's signature Dc(h(Ev))
// this structure has no information that allows us to identify the corresponding
// voter (i.e. findout his username).

typedef struct Voting_Key {
	// voter's public RSA key
	const RSA *pub_RSA;
	int Ev_len;
	const unsigned char *Ev;
	// has this key been disabled due to a conflict?
	bool disabled;
	// voter's secret key Kv
	unsigned char K[16];
	// encrypted ballot 
	unsigned char IVKvB[32];
	// is the encrypted ballot valid?
	bool IVKvB_valid;
	// is the secret key Kv valid?
	bool K_valid;
	// the decrypted ballot
	// this field is valid only when both K and IV,Kv(B) above are valid.
	unsigned long B[2];

	// these are just different signatures of voter used only for
	// publishing online for universal verification.
	int DvhK_valid;
	int len_DvhK;
	unsigned char *DvhK;
	int DvhIVKvB_valid;
	int len_DvhIVKvB;
	unsigned char *DvhIVKvB;
	int len_DvDchEv;
	unsigned char *DvDchEv;
} Voting_Key;

// list of voting keys and everything that we have collected during
// this election under each tallying key. (e.g. encrypted ballots, secret keys and ballots so on.)

static std::list<Voting_Key> voting_keys;

enum serv_state {
	SERV_INIT,
	SERV_REG,
	SERV_TALLY_KEYS,
	SERV_VOTE,
	SERV_TALLY,
	SERV_DONE
};

// current state of the server and the election.
static enum serv_state state = SERV_INIT;
// the number of options voters have when voting. (i.e. the number of different candidates in the election.)
// each option is identified by a number between 0 - (choices - 1)
// this is what voters write on their ballot.
static unsigned int choices = 0;
typedef std::map<int,unsigned char *> password_map;
// the passwords of all known voters
static password_map password;
// the voters who have registered for the election.
// note that this does not mean they have submitted tallying keys (i.e. Ev).
// this just means that we were able to authenticate their username and password
// and that we have signed their blinded tallying key once.
static std::set<int> registered_voters;

// this function publishes what CTF receives from voter's
// for universal verification. it writes its output to file "progress"
// which the administrator can easily put up on the web in real time (i.e.
// voters will be able to monitor the status of the election as things
// unfold and CTF will also not be able to cheat in certain ways.
void
update_progress(int st)
{
	switch (st){
		// write out all eligible voters before we begin voter registration
		case SERV_INIT: {
				FILE *s = fopen("progress", "a");
				fprintf(s, "\n\neligibal voters: (username)\n");
				iterator(password_map, password, I)
					fprintf(s, "%d\n", I->first);
				fclose(s);
				break;
			}
		// write out all those voters who have registered before we start accepting their
		// tallying keys (Ev)
		case SERV_REG: {
				FILE *s = fopen("progress", "a");
				fprintf(s, "\n\nregistered voters: (username)\n");
				iterator(std::set<int>, registered_voters, I)
					fprintf(s, "%d\n", *I);
				fclose(s);
				break;
			}
		// write out the tallying keys with each voter's signature before we start accepting votes.
		case SERV_TALLY_KEYS: {
				FILE *s = fopen("progress", "a");
				fprintf(s, "\n\ntallying keys received: (disabled, Ev, DvDchEv)\n");
				iterator(std::list<Voting_Key>, voting_keys, k){
					//char *sn = BN_bn2hex(k->pub_RSA->n);
					//char *se = BN_bn2hex(k->pub_RSA->e);
					//fprintf(s, "%d, %s, %s\n", k->disabled, se, sn);
					//OPENSSL_free(sn);
					//OPENSSL_free(se);
					fprintf(s, "%d, ", k->disabled);
					for (int i = 0; i < k->Ev_len; i++)
						fprintf(s, "%0.2X", k->Ev[i]);
					fprintf(s, ", ");
					for (int i = 0; i < k->len_DvDchEv; i++)
						fprintf(s, "%0.2X", k->DvDchEv[i]);
					fprintf(s, "\n\n");
				}
				fclose(s);
				break;
			}
		// publish each encrypted vote received under corresponding tallying key
		// along with voter's signature at the end of the voting period.
		case SERV_VOTE: {
				FILE *s = fopen("progress", "a");
				fprintf(s, "\n\nvotes received: (disabled, IVKvB_valid, Ev, DvhIVKvB, IVKvB)\n");
				iterator(std::list<Voting_Key>, voting_keys, k){
					fprintf(s, "%d, %d, ", k->disabled, k->IVKvB_valid);
					for (int i = 0; i < k->Ev_len; i++)
						fprintf(s, "%0.2X", k->Ev[i]);
					fprintf(s, ", ");
					if (k->DvhIVKvB_valid){
						for (int i = 0; i < k->len_DvhIVKvB; i++)
							fprintf(s, "%0.2X", k->DvhIVKvB[i]);
					}
					fprintf(s, ", ");
					if (k->IVKvB_valid){
						for (int i = 0; i < 32; i++)
							fprintf(s, "%0.2X", k->IVKvB[i]);
					}
					fprintf(s, "\n\n");
				}
				fclose(s);
				break;
			}
		// publish each voter's secret key and signature against tallying key
		// just before we wind up the election.
		case SERV_TALLY: {
				FILE *s = fopen("progress", "a");
				fprintf(s, "\n\ntally: (disabled, K_valid, VOTE, Ev, DvhK, K)\n");
				iterator(std::list<Voting_Key>, voting_keys, k){
					fprintf(s, "%d, %d, %d, ", k->disabled, k->K_valid, k->B[0]);
					for (int i = 0; i < k->Ev_len; i++)
						fprintf(s, "%0.2X", k->Ev[i]);
					fprintf(s, ", ");
					if (k->DvhK_valid){
						for (int i = 0; i < k->len_DvhK; i++)
							fprintf(s, "%0.2X", k->DvhK[i]);
					}
					fprintf(s, ", ");
					if (k->K_valid){
						for (int i = 0; i < 16; i++)
							fprintf(s, "%0.2X", k->K[i]);
					}
					fprintf(s, "\n\n");
				}
				fclose(s);
				break;
			}
		default:
			;
	}
}

// check whether username i has been registered once already.
bool
check_registration(int i)
{
	std::set<int>::iterator I = registered_voters.find(i);
	if (I == registered_voters.end())
		return false;
	return true;
}


// check the given password.
bool
check_passwd(int i, char *p)
{
	// check whether the username is valid.
	password_map::iterator I = password.find(i);
	if (I == password.end())
		return false;
	// compute the hash value of password given
	BIGNUM *X = NULL;
	BN_hex2bn(&X, p);
	int len = BN_num_bytes(X);
	unsigned char q[len];
	BN_bn2bin(X, q);
	BN_free(X);
	unsigned char d[SHA_DIGEST_LENGTH];
	assert(SHA1(q, len , d));

	// check against value in password file.
	return memcmp(d, password[i], SHA_DIGEST_LENGTH) == 0;
}


// the main work horse of the server.
// this function handles all messages sent to the server by voters and
// server administrator

MSG *
handle_client_msg(MSG *msg)
{
	switch (MSG_TYPE(msg)){

		// the following messages are sent by the administrator through
		// server-admin program. they have no reply messages and server
		// only responds to a message if it is received at the right time.
		// e.g. no action is taken if SERV_REG message is received while
		// the server is accepting votes (cannot go back in the election).
		// the only exception is DONE message which terminates the
		// election. If the done message is received when we are in the
		// secret key submission phase (i.e. the last phase where voters
		// reveal their secret keys, then we count the ballots and publish
		// final tally. Otherwise we simply shutdown.

		// start voter registration
		case MSG_ADMIN_REG:
				if (state == SERV_INIT){
					state = SERV_REG;
					update_progress(SERV_INIT);
					printf("SERV_REG\n");
				}
				return NULL;
		// stop voter registration and let registered voters
		// submit their tallying keys (i.e. Ev)
		case MSG_ADMIN_TALLY_KEYS:
				if (state == SERV_REG){
					state = SERV_TALLY_KEYS;
					update_progress(SERV_REG);
					printf("SERV_TALLY_KEYS\n");
				}
				return NULL;
		// terminate tallying key submission phase and move on to
		// voting phase.
		case MSG_ADMIN_VOTE:
				if (state == SERV_TALLY_KEYS){
					state = SERV_VOTE;
					update_progress(SERV_TALLY_KEYS);
					printf("SERV_VOTE\n");
				}
				return NULL;
		// stop accepting votes and let voters reveal secret keys
		case MSG_ADMIN_TALLY:
				if (state == SERV_VOTE){
					state = SERV_TALLY;
					update_progress(SERV_VOTE);
					printf("SERV_TALLY\n");
				}
				return NULL;
		// election is over, count all ballots and report final tally
		case MSG_ADMIN_DONE:
				if (state == SERV_TALLY){
					int rejected = 0;
					int *count;
					if (choices > 0)
						count = (int *)calloc(choices, sizeof(int));
					else
						count = NULL;
					int count_all = 0;
					iterator(std::list<Voting_Key>, voting_keys, k){
						if (k->K_valid){
							count_all++;
							if (k->B[0] >= 0 && k->B[0] < choices)
								count[k->B[0]]++;
							else
								rejected++;
						}
					}
					printf("RESULTS:\n");
					for (int i = 0; i < choices; i++)
						printf("%d - %d\n", i, count[i]);
					printf("rejected= %d, count_all= %d\n", rejected, count_all);
					free(count);
				}
				update_progress(state);
				state = SERV_DONE;
				return NULL;

		// the following messages are sent by voters only.
		// voters use client program to send these messages.

		// this message is sent to get CTF's public key.
		// it may be sent at any time during election.
		case MSG_GET_CTF_PUBLIC_KEY: {
				MSG *res = build_ctf_public_key_MSG(CTF_Key);
				return res;
			}

		// this M_1 in the doc.
		// this message is sent to obtain CTF's signature Dc(h(Ev))
		// CTF only responds to this message if it is received during
		// the registration phase.
		case MSG_BLND_SIGN_VOTING_KEY: {
				if (state != SERV_REG)
					return NULL;
				int len1 = *MSG_BODY(msg, 4, int);
				int offset = 12+len1;
				// we first look at voter's username and password.
				BIGNUM *R3 = BN_bin2bn(MSG_BODY(msg, 12+len1, unsigned char), *MSG_BODY(msg, 8+len1, int), NULL);
				BIGNUM *R4 = BN_new();
				// R3 is Ec(h(Ec(R)*h(Ev)), username, password)
				// decrypt R3
				assert(BN_mod_exp(R4, R3, CTF_Key->d, CTF_Key->n, bn_ctx) == 1);
				unsigned char buf2[BN_num_bytes(R4)];
				// now buf2 has the plaintext i.e. h(Ec(R)*h(Ev)), username, password
				BN_bn2bin(R4, buf2);
#define	BUFP(type, offset) ((type *)&buf2[offset+1])
				int uid = *BUFP(int, SHA_DIGEST_LENGTH);
				// make sure this voter has not registered before
				if (check_registration(uid))
					return NULL;
				// check whether password is correct
				if (!check_passwd(uid, BUFP(char, 4+SHA_DIGEST_LENGTH)))
					return NULL;
				// check whether hash in buf2 match with hash computed afresh on Ec(R)*h(Ev)
				unsigned char EcRhEv[SHA_DIGEST_LENGTH];
				assert(SHA1(MSG_BODY(msg, 8, unsigned char), len1, EcRhEv));
				if (memcmp(EcRhEv, BUFP(void, 0), SHA_DIGEST_LENGTH))
					// hash mismatch; so just discard this message
					return NULL;
				// hash match, sign the blind tally key and respond

				// add voter to the list of registered voters so that we do not sign another
				// key for him
				registered_voters.insert(uid);
				// R1 is Ec(R)*h(Ev)
				BIGNUM *R1 = BN_bin2bn(MSG_BODY(msg, 8, unsigned char), len1, NULL);
				BIGNUM *R2 = BN_new();
				// R2 is Dc(Ec(R)*h(Ev)) or R*Dc(h(Ev))
				assert(BN_mod_exp(R2, R1, CTF_Key->d, CTF_Key->n, bn_ctx) == 1);
				// create M_2 (see doc.)
				// M_2 just has R*Dc(h(Ev))
				MSG *res = (MSG *)malloc(sizeof(MSG));
				alloc_msg(8+BN_num_bytes(R2), res);
				MSG_TYPE(res) = MSG_BLND_SIGN_VOTING_KEY_REPL;
				*MSG_BODY(res, 4, int) = BN_bn2bin(R2, MSG_BODY(res, 8, unsigned char));
				BN_free(R1);
				BN_free(R2);
				BN_free(R3);
				BN_free(R4);
				// return M_2 back to voter.
				return res;
			}

		// this is M_3 in the doc.
		// this message is sent to provide CTF with a tallying key Ev
		// CTF will only act on this message if it is received in the tallying key
		// submission period.
		case MSG_VOTING_KEY: {
				// message received at the wrong time, drop it
				if (state != SERV_TALLY_KEYS)
					return NULL;
	
				// extract Ev from M_3
				int Ev_len = *MSG_BODY(msg, 4, int);
				unsigned char *Ev = (unsigned char *)malloc(Ev_len);
				memmove(Ev, MSG_BODY(msg, 8, void), Ev_len);

				// if the CTF accepts the tallying key, it sends response 1 to voter
				// if the tallying key is rejected (only if there is a conflict)
				// it sends back 0.

				MSG *res = (MSG *)malloc(sizeof(MSG));
				alloc_msg(4+4, res);
				MSG_TYPE(res) = MSG_VOTING_KEY_REPL;

				// go through the list of tallying keys submitted thus far and see
				// whether there is a conflict
				iterator(std::list<Voting_Key>, voting_keys, k)
					if (k->Ev_len == Ev_len && memcmp(k->Ev, Ev, Ev_len) == 0){

						// oops! we have a conflict, so disable the conflicting key and
						// reject this key as well (note that we bump off both keys.)
						// we however keep the old key in the list so that we can continue to
						// detect conflicts on this key.
						// why do we bump off both? otherwise we cannot tell who is using
						// this tallying key...
						// we should ideally ask both voters to reveal their private keys
						// at this moment and after they do so, verify their private keys indeed
						// match the rejected tallying key and then ask them to register again.
						// however, we do not do that for now.

						k->disabled = true;
						*MSG_BODY(res, 4, int) = 0;
						return res;
					}

				// there were no conflicts, so initialize libcrypto RSA structs with
				// voters public key (tallying key)
				unsigned char *p = Ev;
				RSA *pub_RSA = d2i_RSAPublicKey(NULL, (const unsigned char **)&p, Ev_len);
				// R1 is Dv(Dc(h(Ev)))
				BIGNUM *R1 = BN_bin2bn(
					MSG_BODY(msg, 4+4+Ev_len+4, unsigned char), 
					*MSG_BODY(msg, 4+4+Ev_len, int), NULL);
				
				// save voter's signature so that we can publish it in file "progress"
				// recall M_3 is (Ev, Dv(Dc(h(Ev))))
				int len_DvDchEv = *MSG_BODY(msg, 4+4+Ev_len, int);
				unsigned char *DvDchEv = (unsigned char *)malloc(len_DvDchEv);
				memmove(DvDchEv, MSG_BODY(msg, 4+4+Ev_len+4, unsigned char), len_DvDchEv);

				// verify CTF's signature
				BIGNUM *R2 = BN_new();
				BIGNUM *R3 = BN_new();
				// R2 is Dc(h(Ev))
				assert(BN_mod_exp(R2, R1, pub_RSA->e, pub_RSA->n, bn_ctx) == 1);
				// R3 is h(Ev)
				assert(BN_mod_exp(R3, R2, CTF_Key->e, CTF_Key->n, bn_ctx) == 1);
				unsigned char hEv[SHA_DIGEST_LENGTH];
				// recompute hash on Ev
				assert(SHA1(Ev, Ev_len, hEv));
				// X is h(Ev)
				BIGNUM *X = BN_bin2bn(hEv, SHA_DIGEST_LENGTH, NULL);
				// check X == R3 ???
				int ret = BN_cmp(X, R3);

				*MSG_BODY(res, 4, int) = !ret;
				if (ret){
					// X <> R3 some wired problem, reply to voter that tallying key was rejected.
					// at this point the voter cannot participate in the election any further.
					printf("REJECT! %d\n", BN_cmp(pub_RSA->n, CTF_Key->n));
					BN_print_fp(stdout, R3);
					printf("\n");
					BN_print_fp(stdout, X);
					printf("\n");

					RSA_free(pub_RSA);
				}
				else {
					// CTF's signature was OK, so save this tallying key.
					Voting_Key Key;
					memset(&Key, 0, sizeof(Key));
					Key.pub_RSA = pub_RSA;
					Key.Ev = Ev;
					Key.Ev_len = Ev_len;
					Key.len_DvDchEv = len_DvDchEv;
					Key.DvDchEv = DvDchEv;
					voting_keys.push_back(Key);

					printf(".%d\n", voting_keys.size());
				}

				BN_free(X);
				BN_free(R1);
				BN_free(R2);
				BN_free(R3);

				return res;
		}

		// this is M_4, we only respond to votes if they are received during the voting phase.
		// M_4 has (Ev, (IV,Kv(B)), Dv(h(IV,Kv(B))))
		case MSG_VOTE: {
				if (state != SERV_VOTE)
					return NULL;

				// extract Ev from the message
				int Ev_len = *MSG_BODY(msg, 4, int);
				unsigned char *Ev = MSG_BODY(msg, 8, unsigned char);

				// find Ev in the list of tallying keys. this is where we keep track of everything
				// about this voter: his encrypted ballot, secret key etc. etc.
				iterator(std::list<Voting_Key>, voting_keys, k){
					// don't look at disabled keys.
					if (!k->disabled && k->Ev_len == Ev_len && memcmp(k->Ev, Ev, Ev_len) == 0){
						// tallying key found.

						k->K_valid = false;
						k->IVKvB_valid = false;
						int offset = 4+4+Ev_len;
						// copy encrypted ballot into our own variables so that we can keep
						// it till the voter reveals his secret key in the next phase.
						memmove(k->IVKvB, MSG_BODY(msg, offset, unsigned char), 32);
						offset += 32;
						unsigned char hIVKvB[SHA_DIGEST_LENGTH];
						// recompute the hash on encrypted ballot IV,Kv(B)
						assert(SHA1((unsigned char *)k->IVKvB, 32, hIVKvB));
						// R is voter's signature i.e. Dv(h(IV,Kv(B)))
						BIGNUM *R = BN_bin2bn(
							MSG_BODY(msg, offset+4, unsigned char),
							*MSG_BODY(msg, offset, int), NULL);

						// save voter's signature for publishing online
						k->len_DvhIVKvB = *MSG_BODY(msg, offset, int);
						k->DvhIVKvB = (unsigned char *)malloc(k->len_DvhIVKvB);
						memmove(k->DvhIVKvB, MSG_BODY(msg, offset+4, unsigned char), k->len_DvhIVKvB);
						k->DvhIVKvB_valid = true;
		
						BIGNUM *R1 = BN_new();
						// decrypt R, R1 is h(IV,Kv(B))
						assert(BN_mod_exp(R1, R, k->pub_RSA->e, k->pub_RSA->n, bn_ctx) == 1);
						// X is recomputed hash on IV,Kv(B)
						BIGNUM *X = BN_bin2bn(hIVKvB, SHA_DIGEST_LENGTH, NULL);
						// if everything is OK then X == R1
						if (BN_cmp(X, R1) == 0)
							// encrypted ballot is accepted.
							k->IVKvB_valid = true;
						else {
							// hash mismatch, reject this ballot
							memset(k->IVKvB, 0, 32);
							printf("VOTE Rejected.\n");
						}
						break;
					}
				}
				return NULL;
			}

		// this is the last message M_5 where the voter reveals his secret key
		// so that CTF can decrypt his ballot. CTF only acts on this message if
		// it is received after the voting phase has concluded.
		// M_5 has format (Ev, Kv, Dv(h(Kv)))
		case MSG_DECRYPT_VOTE: {
				if (state != SERV_TALLY)
					return NULL;
				// as before, first thing is to extract the tallying key (Ev) from the message
				int Ev_len = *MSG_BODY(msg, 4, int);
				unsigned char *Ev = MSG_BODY(msg, 8, unsigned char);
				// go through the list of tallying keys and locate this key.
				iterator(std::list<Voting_Key>, voting_keys, k){
					// we do not look at disabled keys
					if (!k->disabled && k->Ev_len == Ev_len && memcmp(k->Ev, Ev, Ev_len) == 0){
						k->K_valid = false;
						int offset = 4+4+Ev_len;
						// copy the voter's secret key Kv
						memmove(k->K, MSG_BODY(msg, offset, void), sizeof(k->K));
						offset += sizeof(k->K);

						// recompute the hash and verify voter's signature
						unsigned char hK[SHA_DIGEST_LENGTH];
						assert(SHA1((unsigned char *)&k->K, sizeof(k->K), hK));
						// X is h(Kv)
						BIGNUM *X = BN_bin2bn(hK, SHA_DIGEST_LENGTH, NULL);

						// R is voter's signature i.e. Dv(h(Kv))
						BIGNUM *R = BN_bin2bn(
							MSG_BODY(msg, offset+4, unsigned char),
							*MSG_BODY(msg, offset, int), NULL);
						BIGNUM *R1 = BN_new();
						// decrypt R => R1 is h(Kv)
						assert(BN_mod_exp(R1, R, k->pub_RSA->e, k->pub_RSA->n, bn_ctx) == 1);

						// save voter's signature so that we can publish it online
						k->len_DvhK = *MSG_BODY(msg, offset, int);
						k->DvhK = (unsigned char *)malloc(k->len_DvhK);
						memmove(k->DvhK, MSG_BODY(msg, offset+4, unsigned char), k->len_DvhK);
						k->DvhK_valid = true;

						// is X == R1? (i.e. signature OK?)
						// is the encrypted ballot valid? we do not want to try and
						// decrypt invalid ballots just because we got a valid
						// secret key from the voter.
						if (BN_cmp(X, R1) == 0 && k->IVKvB_valid){
							k->K_valid = true;

							// use 128 bit AES to decrypt ballot using Kv just received.
							// we decrypt the ballot here and store it in k->B[0].
							// the ballot will be counted when the final tallying is done
							// just before server shutdown.
							AES_KEY dec;
							assert(AES_set_decrypt_key(k->K, 128, &dec) == 0);
							unsigned char IV[16];
							memmove(IV, k->IVKvB, 16);
							AES_cbc_encrypt(&k->IVKvB[16], 
								(unsigned char *)k->B, 16, &dec, IV, AES_DECRYPT);

							// ah! finally the ballot
							printf("B= %d\n", k->B[0]);
						}
						else
							printf("K/IV Rejected.\n");

						BN_free(X);
						BN_free(R);
						BN_free(R1);

						break;
					}
				}
				return NULL;
			}

		default:
			printf("ERROR: MSG_TYPE= %d UNKNOWN!\n", MSG_TYPE(msg));
			return NULL;
	}
}


// handle one client connection
void
handle_client(BIO *cbio)
{
	MSG msg;
	// read the client's message into msg
	// if there was a problem we just return for there is nothing
	// more we can do in that case
	if (read_msg(cbio, &msg))
		return;
	// call handle_client_msg to take appropriate action for
	// this message. Now these messages can come from both voters as well
	// as administrator. 
	// if we need to send a response, handle_client_msg will construct
	// that response and return it to us here. we send the response
	// over the same connection
	MSG *res = handle_client_msg(&msg);
	free(msg.data);
	// check whether there is a response, not all messages have corresponding
	// reply messages
	if (res){
		// write the response
		write_msg(cbio, res);
		free(res->data);
		free(res);
	}
}


// read password file and populate map password with passwords.
// voter with username i (recall usernames are just integers)
// has his password stored in password[i]
void
read_mypasswd(void)
{
	FILE *s = fopen("mypasswd", "r");
	if (!s)
		abort();
	int i;
	char sY[1024];
	while (fscanf(s, "%d %s\n", &i, &sY) == 2){
		BIGNUM *Y = NULL;
		BN_hex2bn(&Y, sY);
		unsigned char *d = (unsigned char *)malloc(SHA_DIGEST_LENGTH);
		assert(BN_num_bytes(Y) == SHA_DIGEST_LENGTH);
		BN_bn2bin(Y, d);
		password[i] = d;
		//printf("%d %s %s\n", i, sY, BN_bn2hex(Y));
		BN_free(Y);
	}
	fclose(s);
}


#include <unistd.h>

int
main(int argc, char *argv[])
{
	// initialize the progress file
	// this file could be published online so that voters can monitor
	// the progress of the election as it unfolds
	system("date >progress");

	// number of choices voters have when voting?
	// voters can choose any number between 0 and choices-1
	// this number is what is written on their ballot
	if (argc != 2 || sscanf(argv[1], "--choices=%d", &choices) != 1)
		abort();

	// read the password file. 
	// this file has to be in the same directory as the server's working
	// directory and must have the name mypasswd
	read_mypasswd();

	// initialize openssl libcrypto
	ERR_load_crypto_strings();

	bn_ctx = BN_CTX_new();

	// check whether openssl's random number generator is working
	assert(RAND_status() == 1);

	// generate CTF's public/private keys. CTF's modulus has size 1024 bits
	// his public exponent is 17
	CTF_Key = RSA_generate_key(1024, 17, NULL, NULL);
	if (CTF_Key == NULL){
		ERR_print_errors_fp(stdout);
		return -1;
	}

	// the server listens on port 8081
	BIO *abio = BIO_new_accept((char *)"8081");
	BIO_set_nbio_accept(abio, 0);

	BIO_set_bind_mode(abio, BIO_BIND_REUSEADDR);
	if (BIO_do_accept(abio) <= 0){
		ERR_print_errors_fp(stderr);
		abort();
	}


	while (state != SERV_DONE && (BIO_do_accept(abio) > 0)){
		BIO *cbio;
		while (state != SERV_DONE && (cbio = BIO_pop(abio))){
			// when a client makes a connection we handle that connection
			// we handle one client at a time
			handle_client(cbio);
			BIO_free(cbio);
		}
	}

//	int s;
//	if (BIO_get_fd(abio, &s) != -1)
//		close(s);

//	BIO_reset(abio);
	BIO_free(abio);

	return 0;
}


